package Main;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Vector;

import Commands.Command;
import Commands.PINCmd;
import Commands.PINSCmd;
import GPIO.GPIOControl;
import Networking.Server;
import Networking.ServerReceiver;

public class RaspiServer implements ServerReceiver {

	/** The server to get commands */
	Server server;

	/** Indicator if GPIOs should be used or not */
	private boolean useGPIOs = false;

	/** Command List */
	private Vector<Command> commands = new Vector<Command>();

	/**
	 * @param useGPIO
	 *            Set this to use GPIOs or just create a server
	 */
	public RaspiServer(boolean useGPIO) {
		try {
			// Initialize GPIOs
			useGPIOs = useGPIO;
			if (useGPIOs) {
				log("Initlializing GPIOs");
				GPIOControl.initialize();
				log("GPIOs OK");
			}

			// Create server
			server = new Server(this);
			log("Starting Server...");
			new Thread(server).start();
			log("Server started");
			log(server.getIPAddress());

			commands.add(new PINSCmd());
			commands.add(new PINCmd());

		} catch (IOException e) {
			log("Starting server failed!");
		}
	}

	/**
	 * This should be called on application exit
	 */
	public void exit() {
		if (useGPIOs) {
			GPIOControl.shutdown();
		}
	}

	/**
	 * Logs the given String in console. It adds the date and time in front of
	 * the given text
	 * 
	 * @param log
	 *            The text to log
	 */
	public void log(String log) {
		String timeStamp = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss -   ")
				.format(Calendar.getInstance().getTime());

		System.out.println(timeStamp + log);
	}

	/**
	 * Validates the given line if it is a command
	 * 
	 * @param cmd
	 *            The line to check
	 * @return The command that has been found. null if invalid command
	 */
	public Command validateCommand(String cmd) {

		for (int i = 0; i < commands.size(); i++) {

			// Check if the sent command is current command in loop
			String cmdStr = commands.get(i).getCommandString();
			if (cmd.startsWith(cmdStr)) {
				return commands.get(i);
			}
		}

		return null;
	}

	@Override
	public void lineReceived(String line) {
		try {
			Command cmd = validateCommand(line);

			if (cmd != null) {
				// Get command and command-string
				String cmdStr = cmd.getCommandString();

				// Validating parameter
				cmd.validateOptions(line.substring(cmdStr.length() + 1,
						line.length()));

				// Executing command
				cmd.execute();
				log(line);

				// Send result to client if available
				String result = cmd.getResult();
				if (!result.isEmpty()) {
					log(result);
					server.sendLine(result);
				}

			} else {
				// Invalid Command
				log("Invalid command: " + line);
			}
		} catch (Exception e) {
			log(e.getMessage() + " (" + line + ")");
		}
	}

	@Override
	public void clientConnected(String clientIP) {
		log("Client connected (" + clientIP + ")");
	}

	@Override
	public void clientDisconnected(String clientIP) {
		log("Client disconnected (" + clientIP + ")");
	}

	@Override
	public void clientConnectionLost(String clientIP, String msg) {
		log("Client lost connection (" + clientIP + "): \"" + msg + "\"");
	}

}
